#pragma once
#include <iostream>
#include <cerrno>
#include <unistd.h>
#include <string>
#include <strings.h>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstdio>
#include <vector>
#include "Log.hpp"
#include "Comm.hpp"
#include "sockaddr.hpp"
#define BUFFERSIZE 1024

// 转换命令
class Command
{
public:
    Command(std::string command)
        : _command(command)
        , _not_command({"rm",
                        "unlink",
                        "shutdown",
                        "cp",
                        "mv"})
    {}
    ~Command()
    {}

    bool Check()
    {
        for (auto &e : _not_command)
        {
            if (_command.find(e) != std::string::npos)
            {
                return false;
            }
        }
        return true;
    }

    std::string Command_To_Result()
    {
        std::string retstr;
        char buffer[1024];

        if (!Check()) return "bad man!";
        else
        {
            FILE *pf = popen(_command.c_str(), "r");
            if (pf == nullptr)
            {
                _log.LogMessage(ClassFile, Error, "Command to Result error -> errno : %d strerror : %s\n", errno, strerror(errno));
                exit(CommandToResultError);
            }
            while(true)
            {
                char* s = fgets(buffer, sizeof(buffer), pf);
                if(!s) break;
                retstr += buffer;
            }
            pclose(pf);
        }

        return retstr.empty() ? "success" : retstr; 
    }

private:
    std::string _command;
    std::vector<std::string> _not_command;
};

class UDP_server
{
public:
    UDP_server(in_port_t server_port)
        : _sockfd(-1), _sk(server_port)
    {
    }

    ~UDP_server()
    {
    }

    // 初始化server端
    void Init()
    {
        // 创建socket
        _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
        if (_sockfd == -1)
        {
            _log.LogMessage(ClassFile, Error, "server socket error -> errno : %d strerror : %s\n", errno, strerror(errno));
            exit(SocketError);
        }
        _log.LogMessage(ClassFile, Info, "server socket success, _fd = %d\n", _sockfd);

        // 绑定网络信息
        int ret = ::bind(_sockfd, (const struct sockaddr *)(&_sk.addr_in()), _sk.len());
        if (ret == -1)
        {
            _log.LogMessage(ClassFile, Error, "server bind error -> errno : %d strerror : %s\n", errno, strerror(errno));
            exit(BindError);
        }
    }

    // 接收网络信息
    void Start()
    {
        sleep(5);
        char buffer[BUFFERSIZE];
        // 服务端一直运行，不退出，除非我们人为退出
        while (true)
        {
            // 输出型参数，获取到客户端的套接字信息

            struct sockaddr_in client;
            socklen_t client_len = sizeof(client);
            ssize_t ret = recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)(&client), &client_len);

            Sockaddr tmp(client);
            if (ret > 0)
            {
                buffer[ret] = 0;
                std::cout << tmp.PrintDebug() << ": " << buffer << std::endl;

                // 处理命令
                Command command(buffer);
                std::string result = command.Command_To_Result();
                

                // 将结果发送给client
                ssize_t ret2 = sendto(_sockfd, result.c_str(), result.size(), 0, (const sockaddr *)(&client), client_len);
                if (ret2 == -1)
                {
                    _log.LogMessage(ClassFile, Error, "server sendto error -> errno : %d strerror : %s\n", errno, strerror(errno));
                    exit(SendtoError);
                }
            }
        }
    }

private:
    int _sockfd;
    Sockaddr _sk; // 初始化sockaddr
};
